// 算法：一个矩阵的鞍点是指：鞍点位置上的元素在该行上最大，在该列上最小。
//       按行扫描矩阵，提取出当前i行作为一个一维数组，
//       找到其最大值位置cpos，
//       在矩阵的转置矩阵中按行扫描矩阵，取出第cpos行的数据
//       作为一个一维数组，找到其最小值位置rpos。
//       在矩阵的第cpos列中找到找到其最小值位置rpos。
//       若rpos等当前行i，则是一个鞍点。
//       需要注意，一个矩阵可以有多个鞍点
// 参数：
	
src/chap08/ex08-37YangHuiTriangle/03yanghuitriangle2Ddynamic.c
/*--------------------------------------------------------------------------------
* Copyright (c) 2020,西北农林科技大学信息学院计算机科学系
* All rights reserved.
*
* 文件名称：01yanguyuitriangle2D.c
* 文件标识：见配置管理计划书
* 摘要：杨辉三角形(Pascal Triangle)的C语言二维数组实现，
*       主要演示用指针数组管理二维动态数组的操作。
*
* 当前版本：1.0
* 作者：耿楠
* 完成日期：2020年11月30日
*
* 取代版本：无
* 原作者：耿楠
* 完成日期：2020年11月30日
------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>

// 构建杨辉三角形
unsigned int **create_yanghui(size_t);
// 销毁杨辉三角形
void destory_yanghui(unsigned int **, size_t);

// 输出杨辉三角形
void print_yanghui(unsigned int **, size_t);

// 统计一个正整数的位数
size_t get_number_length(unsigned int);

int main()
	@@ -26,12 +47,23 @@ int main()
	return 0;
}

//-----------------------------------------------------------------------------------------------
// 名称：unsigned int **create_yanghui(size_t num)
// 功能：构建杨辉三角形(指针数组管理二维数组，内存不一定连续)
// 算法：用二维数组存储各元素，则yh[i][j] = yh[i - 1][j - 1]+ yh[i - 1][j]。
// 参数：
//       [size_t num] --- 二维数组的行数
// 返回：[unsigned int **] --- 指针数组的首地址
// 作者：耿楠
// 日期：2020年11月30日
//-----------------------------------------------------------------------------------------------
unsigned int **create_yanghui(size_t num)
{
	int r, c;

	unsigned int **p = NULL;

        // 创建指针数组(二维数组各行)
	p = (unsigned int **)calloc(sizeof(unsigned int *), num); // calloc同时清零

	if(p == NULL)
	@@ -40,6 +72,7 @@ unsigned int **create_yanghui(size_t num)
		exit(1);
	}

        // 创建一维数组(二维数组各列)
	for(r = 0; r < num; r++)
	{
		*(p + r) = (unsigned int *)calloc(sizeof(unsigned int), r + 1);
	@@ -51,6 +84,7 @@ unsigned int **create_yanghui(size_t num)

		for(c = 0; c <= r; c++)
		{
		        // 计算杨辉值
			p[r][c] = (r == c || c == 0) ? 1: p[r - 1][c - 1] + p[r - 1][c];
		}
	}
	@@ -58,18 +92,41 @@ unsigned int **create_yanghui(size_t num)
	return p;
}

//-----------------------------------------------------------------------------------------------
// 名称：void destory_yanghui(unsigned int **pyh, size_t num)
// 功能：销毁杨辉三角形(指针数组管理二维数组，内存不一定连续)
// 算法：先销毁各行，再销毁指针数组。
// 参数：
//       [unsigned int **pyh] --- 指针数组的首地址
//       [size_t num] --- 二维数组的行数
// 返回：[unsigned int **] --- 指针数组的首地址
// 作者：耿楠
// 日期：2020年11月30日
//-----------------------------------------------------------------------------------------------
void destory_yanghui(unsigned int **pyh, size_t num)
{
	int r;

        // 先销毁行
	for(r = 0; r < num; r++)
	{
		free(*(pyh + r));
	}

        // 再销毁列
	free(pyh);
}

//-----------------------------------------------------------------------------------------------
// 名称：size_t get_number_length(unsigned int num)
// 功能：判断一个正整数由几位数字构成
// 算法：不断除10，直到为0，统计循环次数。
// 参数：
//       [unsigned int num] --- 需要判断的正整数
// 返回：[size_t] --- 数字个数
// 作者：耿楠
// 日期：2020年11月30日
//-----------------------------------------------------------------------------------------------
size_t get_number_length(unsigned int num)
{
	int cnt = 1;
	@@ -83,14 +140,27 @@ size_t get_number_length(unsigned int num)
}

// 可奇偶数位置不同颜色/字符输出，以形成谢宾斯基垫片(数据驱动概念)
//-----------------------------------------------------------------------------------------------
// 名称：void print_yanghui(unsigned int **pyh, size_t num)
// 功能：输出杨辉三角形
// 算法：通过添加必要的空白，按等腰三角形的形式输出杨辉三角形。
//       可奇偶数位置不同颜色/字符输出，通过数据驱动生成谢尔宾斯基垫片
// 参数：
//       [unsigned int **pyh] --- 指针数组的首地址
//       [size_t num] --- 二维数组的行数
// 返回：无
// 作者：耿楠
// 日期：2020年11月30日
//-----------------------------------------------------------------------------------------------
void print_yanghui(unsigned int **pyh, size_t num)
{
	int i, j;
	int r, c;
	size_t len = 1;
	size_t len = 1; // 单个元素占有字符长度

	for(r = 0; r < num; r++)
	{
	        // 为指定行添加前导空格
		for(i = 0; i < num - r - 1; i++)
		{
			for (j = 0; j < len; j++)
	@@ -99,18 +169,23 @@ void print_yanghui(unsigned int **pyh, size_t num)
			}
		}

                // 输出图案
		for(c = 0; c < r + 1; c++)
		{
			if(pyh[r][c] % 2 == 0)
			{
			        // 偶数用红色输出字符'O'
				printf("\033[31mO\033[0m");
				// 偶数输出字符'*'
				/* printf("*"); */
			}
			else
			{
			        // 偶数用输出字符'O'
				printf("O");
			}

			
			// 字符间补齐空格
			for(j = 0; j < len; j++)
			{
				printf(" ");
